home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsconsist / fsconsistIOClient.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-10  |  13.8 KB  |  489 lines

  1. /* 
  2.  * fsIOClient.c --
  3.  *
  4.  *    Routines to handle the client lists at the I/O handle level.  
  5.  *    The I/O handle client list is needed for cache consistency and to
  6.  *    verify that client's are valid.  The routines here add and remove
  7.  *    clients.
  8.  *    (Note that fsCacheConsist.c has routines which also use the client
  9.  *    list on the I/O handle, but those routines are specific to files.)
  10.  *
  11.  *    A master list of clients is also kept here to simplify cleaning
  12.  *    up after crashed clients.  Periodically this master list is checked
  13.  *    and the file state for dead clients is cleaned up.
  14.  *
  15.  * Copyright 1987 Regents of the University of California
  16.  * All rights reserved.
  17.  * Permission to use, copy, modify, and distribute this
  18.  * software and its documentation for any purpose and without
  19.  * fee is hereby granted, provided that the above copyright
  20.  * notice appear in all copies.  The University of California
  21.  * makes no representations about the suitability of this
  22.  * software for any purpose.  It is provided "as is" without
  23.  * express or implied warranty.
  24.  */
  25.  
  26. #ifndef lint
  27. static char rcsid[] = "$Header: /sprite/src/kernel/fsconsist/RCS/fsconsistIOClient.c,v 9.6 90/10/08 12:29:48 mendel Exp $ SPRITE (Berkeley)";
  28. #endif not lint
  29.  
  30.  
  31. #include <sprite.h>
  32. #include <fs.h>
  33. #include <fsutil.h>
  34. #include <fsio.h>
  35. #include <fsconsist.h>
  36. #include <fsStat.h>
  37. #include <stdlib.h>
  38. #include <rpc.h>
  39.  
  40. #include <stdio.h>
  41. /*
  42.  * A master list of clients of this host.  This is maintained here and
  43.  * consulted periodically in order to be able to clean up after dead clients.
  44.  */
  45. static List_Links masterClientListHdr;
  46. static List_Links *masterClientList;
  47.  
  48. typedef struct {
  49.     List_Links    links;
  50.     int        clientID;
  51. } ClientItem;
  52.  
  53. static Sync_Lock clientLock;
  54. #define LOCKPTR (&clientLock)
  55.  
  56.  
  57. /*
  58.  * ----------------------------------------------------------------------------
  59.  *
  60.  * Fsconsist_ClientInit --
  61.  *
  62.  *    Initialize the master list of clients for this server.
  63.  *
  64.  * Results:
  65.  *    None.
  66.  *
  67.  * Side effects:
  68.  *    List_Init.
  69.  *
  70.  * ----------------------------------------------------------------------------
  71.  */
  72.  
  73. void
  74. Fsconsist_ClientInit()
  75. {
  76.     Sync_LockInitDynamic(&clientLock, "Fs:clientLock");
  77.     List_Init(&masterClientListHdr);
  78.     masterClientList = &masterClientListHdr;
  79. }
  80.  
  81.  
  82. /*
  83.  * ----------------------------------------------------------------------------
  84.  *
  85.  * Fsconsist_IOClientOpen --
  86.  *
  87.  *    Add the client to the set of clients doing I/O on a file.  This
  88.  *    increments reference counts due to the client.
  89.  *
  90.  * Results:
  91.  *    Returns a pointer to the client state just added.  This is used
  92.  *    by the file consistency routines, which set the cached boolean
  93.  *    and the openTimeStamp, but ignored by others.
  94.  *
  95.  * Side effects:
  96.  *    As well as adding the client to the set of clients for the I/O handle,
  97.  *    the client is recorded in the master list of clients (if it isn't
  98.  *    already there) so clients can be easily scavenged.
  99.  *
  100.  * ----------------------------------------------------------------------------
  101.  */
  102.  
  103. ENTRY Fsconsist_ClientInfo *
  104. Fsconsist_IOClientOpen(clientList, clientID, useFlags, cached)
  105.     List_Links    *clientList;    /* List of clients for the I/O handle. */
  106.     int        clientID;    /* The client who is opening the file. */
  107.     int        useFlags;    /* FS_READ | FS_WRITE | FS_EXECUTE */
  108.     Boolean    cached;        /* Boolean property recorded for client */
  109. {
  110.     register Fsconsist_ClientInfo *clientPtr;
  111.  
  112.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  113.     if (clientPtr->clientID == clientID) {
  114.         goto found;
  115.     }
  116.     }
  117.     INSERT_CLIENT(clientList, clientPtr, clientID);
  118. found:
  119.     clientPtr->cached = cached;
  120.     clientPtr->use.ref++;
  121.     if (useFlags & FS_WRITE) {
  122.     clientPtr->use.write++;
  123.     }
  124.     if (useFlags & FS_EXECUTE) {
  125.     clientPtr->use.exec++;
  126.     }
  127.  
  128.     /*
  129.      * Make sure the client is in the master list of all clients for this host.
  130.      */
  131.     Fsconsist_AddClient(clientID);
  132.     return(clientPtr);
  133. }
  134.  
  135. /*
  136.  * ----------------------------------------------------------------------------
  137.  *
  138.  * 
  139.  Fsconsist_IOClientReopen --
  140.  *
  141.  *    Add the client to the set of clients doing I/O on a file.  This
  142.  *    updates reference counts due to the client's reopen attempt.
  143.  *
  144.  * Results:
  145.  *    TRUE if the client was already listed.
  146.  *
  147.  * Side effects:
  148.  *    As well as adding the client to the set of clients for the I/O handle,
  149.  *    the client is recorded in the master list of clients (if it isn't
  150.  *    already there) so clients can be easily scavenged.
  151.  *
  152.  * ----------------------------------------------------------------------------
  153.  */
  154.  
  155. Boolean
  156. Fsconsist_IOClientReopen(clientList, clientID, usePtr)
  157.     List_Links    *clientList;    /* List of clients for the I/O handle. */
  158.     int        clientID;    /* The client who is opening the file. */
  159.     Fsio_UseCounts    *usePtr;    /* In - Client's usage of the object.
  160.                  * Out - difference between old client useage.
  161.                  *  This means that the summary use counts
  162.                  *  can be updated by adding the use counts
  163.                  *  left over in this structure after the
  164.                  *  reconciliation with the old state. */
  165. {
  166.     register Fsconsist_ClientInfo *clientPtr;
  167.     register Boolean found = FALSE;
  168.  
  169.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  170.     if (clientPtr->clientID == clientID) {
  171.         found = TRUE;
  172.         goto doit;
  173.     }
  174.     }
  175.     INSERT_CLIENT(clientList, clientPtr, clientID);
  176. doit:
  177.     clientPtr->use.ref += usePtr->ref;
  178.     clientPtr->use.write += usePtr->write;
  179.     clientPtr->use.exec += usePtr->exec;
  180.     /*
  181.      * Make sure the client is in the master list of all clients for this host.
  182.      */
  183.     Fsconsist_AddClient(clientID);
  184.     return(found);
  185. }
  186.  
  187. /*
  188.  * ----------------------------------------------------------------------------
  189.  *
  190.  * Fsconsist_IOClientClose --
  191.  *
  192.  *    Decrement the reference, executor and/or writer counts for the client 
  193.  *    for the given handle.  Note, we don't mess with the master list of
  194.  *    clients.  That gets cleaned up by Fsconsist_ClientScavenge.
  195.  *
  196.  * Results:
  197.  *    TRUE if there was a record that the client was using the file.
  198.  *    This is used to trap out invalid closes.
  199.  *
  200.  * Side effects:
  201.  *    The client list entry from the stream is removed.
  202.  *
  203.  * ----------------------------------------------------------------------------
  204.  *
  205.  */
  206. Boolean
  207. Fsconsist_IOClientClose(clientList, clientID, flags, cachePtr)
  208.     List_Links        *clientList;    /* List of clients for I/O handle */
  209.     int            clientID;    /* Host ID of client that had it open */
  210.     register int    flags;        /* Flags from the stream. */
  211.     Boolean        *cachePtr;    /* In/Out.  If TRUE on entry, this won't
  212.                      * delete the client list entry if
  213.                      * the entry's cached field is also
  214.                      * TRUE.  On return, this is the value
  215.                      * of the client's cached field. */
  216. {
  217.     register    Fsconsist_ClientInfo    *clientPtr;
  218.     register    Boolean        found = FALSE;
  219.  
  220.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  221.     if (clientPtr->clientID == clientID) {
  222.         found = TRUE;
  223.         break;
  224.     }
  225.     }
  226.     if (found) {
  227.     if ((clientPtr->use.ref < 0) || (clientPtr->use.write < 0) ||
  228.         (clientPtr->use.exec < 0)) {
  229.         printf("Fsconsist_IOClientClose: Values are bad at start:\n");
  230.         panic("Fsconsist_IOClientClose: client %d ref %d write %d exec %d\n",
  231.         clientPtr->clientID,
  232.         clientPtr->use.ref, clientPtr->use.write, clientPtr->use.exec);
  233.     }
  234.     clientPtr->use.ref--;
  235.     if (flags & FS_WRITE) {
  236.         clientPtr->use.write--;
  237.     }
  238.     if (flags & FS_EXECUTE) {
  239.         clientPtr->use.exec--;
  240.     }
  241.     if ((clientPtr->use.ref < 0) || (clientPtr->use.write < 0) ||
  242.         (clientPtr->use.exec < 0)) {
  243.         printf("This is (probably) a continuable panic.\n");
  244.         panic("Fsconsist_IOClientClose: client %d ref %d write %d exec %d\n",
  245.         clientPtr->clientID,
  246.         clientPtr->use.ref, clientPtr->use.write, clientPtr->use.exec);
  247.         clientPtr->use.exec = 0;
  248.     }
  249.     if ((!(*cachePtr) || !clientPtr->cached) &&
  250.         (clientPtr->use.ref == 0)) {
  251.         *cachePtr = clientPtr->cached;
  252.         if (!clientPtr->locked) {
  253.         /*
  254.          * Free up the client list entry if it is not locked
  255.          * due to an iteration through the client list.
  256.          */
  257.         REMOVE_CLIENT(clientPtr);
  258.         }
  259.     } else {
  260.         *cachePtr = clientPtr->cached;
  261.     }
  262.     }
  263.     return(found);
  264. }
  265.  
  266. /*
  267.  * ----------------------------------------------------------------------------
  268.  *
  269.  * Fsconsist_IOClientRemoveWriter --
  270.  *
  271.  *    Decrement the writer count for the client for the given handle.
  272.  *    This is done when a writer of a stream (for instance, a pipe)
  273.  *    becomes only a reader.
  274.  *
  275.  * Results:
  276.  *    TRUE if there was a record that the client was using the file.
  277.  *    This is used to trap out invalid closes.
  278.  *
  279.  * Side effects:
  280.  *    None.
  281.  *
  282.  * ----------------------------------------------------------------------------
  283.  *
  284.  */
  285. Boolean
  286. Fsconsist_IOClientRemoveWriter(clientList, clientID)
  287.     List_Links        *clientList;    /* List of clients for I/O handle */
  288.     int            clientID;    /* Host ID of client that had it open */
  289. {
  290.     register    Fsconsist_ClientInfo    *clientPtr;
  291.     register    Boolean        found = FALSE;
  292.  
  293.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  294.     if (clientPtr->clientID == clientID) {
  295.         found = TRUE;
  296.         break;
  297.     }
  298.     }
  299.     if (found) {
  300.     clientPtr->use.write--;
  301.     if (clientPtr->use.write < 0) {
  302.         panic("Fsconsist_IOClientRemoveWriter: client %d ref %d write %d exec %d\n",
  303.         clientPtr->clientID,
  304.         clientPtr->use.ref, clientPtr->use.write, clientPtr->use.exec);
  305.     }
  306.     }
  307.     return(found);
  308. }
  309.  
  310. /*
  311.  * ----------------------------------------------------------------------------
  312.  *
  313.  * Fsconsist_ClientScavenge --
  314.  *
  315.  *      Check the master list of clients for ones that have crashed.  If any
  316.  *    one has then we call Fsutil_RemoveClient to clean up the file state
  317.  *    associated with it.
  318.  *
  319.  *    NOT USED.  File servers let regular traffic, like consistency
  320.  *    call backs, detect failures.
  321.  *
  322.  * Results:
  323.  *    None.
  324.  *
  325.  * Side effects:
  326.  *    Calls FsClientRemove on dead clients, and nukes them from the
  327.  *    master client list.
  328.  *
  329.  * ----------------------------------------------------------------------------
  330.  *
  331.  */
  332. #ifdef notdef
  333. ENTRY void
  334. Fsconsist_ClientScavenge()
  335. {
  336.     register    ClientItem    *listPtr;
  337.  
  338.     LOCK_MONITOR;
  339.  
  340.     LIST_FORALL(masterClientList, (List_Links *)listPtr) {
  341.     if (listPtr->clientID != rpc_SpriteID && 
  342.         Recov_IsHostDown(listPtr->clientID)) {
  343.         Fsutil_RemoveClient(listPtr->clientID);
  344.     }
  345.     }
  346.  
  347.     UNLOCK_MONITOR;
  348. }
  349. #endif notdef
  350.  
  351. /*
  352.  * ----------------------------------------------------------------------------
  353.  *
  354.  * Fsconsist_IOClientKill --
  355.  *
  356.  *    Find and remove the given client in the list for the handle.  The
  357.  *    number of client references, writers, and executers is returned
  358.  *    so our caller can clean up the reference counts in the handle.
  359.  *
  360.  * Results:
  361.  *    *inUsePtr set to TRUE if the client has the file open, *writingPtr
  362.  *    set to TRUE if the client has the file open for writing, and 
  363.  *    *executingPtr set to TRUE if the client has the file open for
  364.  *    execution.
  365.  *    
  366.  * Side effects:
  367.  *    None.
  368.  *
  369.  * ----------------------------------------------------------------------------
  370.  *
  371.  */
  372. void
  373. Fsconsist_IOClientKill(clientList, clientID, refPtr, writePtr, execPtr)
  374.     List_Links *clientList;    /* List of clients to a file. */
  375.     int        clientID;    /* Client to delete. */
  376.     int        *refPtr;    /* Number of times client has file open. */
  377.     int        *writePtr;    /* Number of times client is writing file. */
  378.     int        *execPtr;    /* Number of times clients is executing file.*/
  379. {
  380.     register Fsconsist_ClientInfo     *clientPtr;
  381.  
  382.     *refPtr = 0;
  383.     *writePtr = 0;
  384.     *execPtr = 0;
  385.  
  386.     /*
  387.      * Remove the client from the list of clients using the file.
  388.      */
  389.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  390.     if (clientPtr->clientID == clientID) {
  391.         *refPtr += clientPtr->use.ref;
  392.         *writePtr += clientPtr->use.write;
  393.         *execPtr += clientPtr->use.exec;
  394.         if (clientPtr->locked) {
  395.         clientPtr->use.ref = 0;
  396.         clientPtr->use.write = 0;
  397.         clientPtr->use.exec = 0;
  398.         } else {
  399.         REMOVE_CLIENT(clientPtr);
  400.         }
  401.         break;
  402.     }
  403.     }
  404.  
  405. }
  406.  
  407. /*
  408.  * ----------------------------------------------------------------------------
  409.  *
  410.  * Fsconsist_IOClientStatus --
  411.  *
  412.  *    This computes the difference between a client's version of its
  413.  *    state and our version of the client's usage state.  This is called
  414.  *    during a device reopen to see how the client's state is different.
  415.  *
  416.  * Results:
  417.  *    The client's version of the use state is modified to reflect
  418.  *    the difference between our previous notion of the state and
  419.  *    the client's notion of the state.  This means that the ref, write,
  420.  *    and exec fields can be positive or negative after this call.
  421.  *    If they are zero then the client's state matches ours.
  422.  *    
  423.  * Side effects:
  424.  *    None.
  425.  *
  426.  * ----------------------------------------------------------------------------
  427.  *
  428.  */
  429. void
  430. Fsconsist_IOClientStatus(clientList, clientID, clientUsePtr)
  431.     List_Links *clientList;    /* List of clients to a file. */
  432.     int        clientID;    /* Client to check. */
  433.     Fsio_UseCounts    *clientUsePtr;    /* Client's version of the usage */
  434. {
  435.     register Fsconsist_ClientInfo     *clientPtr;
  436.  
  437.     LIST_FORALL(clientList, (List_Links *) clientPtr) {
  438.     if (clientPtr->clientID == clientID) {
  439.         clientUsePtr->ref -= clientPtr->use.ref;
  440.         clientUsePtr->write -= clientPtr->use.write;
  441.         clientUsePtr->exec -= clientPtr->use.exec;
  442.         return;
  443.     }
  444.     }
  445. }
  446.  
  447.  
  448. /*
  449.  * ----------------------------------------------------------------------------
  450.  *
  451.  * Fsconsist_AddClient --
  452.  *
  453.  *      Add a client to the master list of clients that is checked by
  454.  *    Fsconsist_ClientScavenge.
  455.  *
  456.  * Results:
  457.  *    None.
  458.  *
  459.  * Side effects:
  460.  *    May add the client to the list.
  461.  *
  462.  * ----------------------------------------------------------------------------
  463.  *
  464.  */
  465. /*ARGSUSED*/
  466. ENTRY void
  467. Fsconsist_AddClient(clientID)
  468.     int clientID;
  469. {
  470. #ifdef notdef
  471.     register    ClientItem    *listPtr;
  472.  
  473.     LOCK_MONITOR;
  474.  
  475.     LIST_FORALL(masterClientList, (List_Links *)listPtr) {
  476.     if (listPtr->clientID == clientID) {
  477.         goto exit;
  478.     }
  479.     }
  480.     listPtr = mnew(ClientItem);
  481.     listPtr->clientID = clientID;
  482.     List_InitElement((List_Links *)listPtr);
  483.     List_Insert((List_Links *)listPtr, LIST_ATFRONT(masterClientList));
  484. exit:
  485.     UNLOCK_MONITOR;
  486. #endif notdef
  487. }
  488.  
  489.